/* readline.c  
 * 
 * Adapted from the original version by 
 * Jon C. Snader: Effective TCP/IP Programming
 *           Addison-Wesley 2000
 */

#include	<stdio.h>
#include <errno.h>
#include <sys/socket.h>

/* readline - read a '\n' terminated line from socket fd 
              into buffer bufptr of size len. The line in the
              buffer is terminated with '\0'.
              It returns -1 in case of error or if
              the capacity of the buffer is exceeded.
	      It returns 0 if EOF is encountered before reading '\n'.
 */
int readline( int fd, char *bufptr, size_t len )
{
  /* Note that this function is very tricky.  It uses the
     static variables bp, cnt, and b to establish a local buffer.
     The recv call requests large chunks of data (the size of the buffer).
     Then if the recv call reads more than one line, the overflow
     remains in the buffer and it is made available to the next call
     to readline. 
     Notice also that this routine reads up to '\n' and overwrites
     it with '\0'. Thus if the line is really terminated with
     "\r\n", the '\r' will remain unchanged.
  */
  char *bufx = bufptr;
  static char *bp;
  static int cnt = 0;
  static char b[ 1500 ];
  char c;
  
  while ( --len > 0 )
    {
      if ( --cnt <= 0 )
	{
	  cnt = recv( fd, b, sizeof( b ), 0 );
	  if ( cnt < 0 )
	    {
	      if ( errno == EINTR )
		{
		  len++;		/* the while will decrement */
		  continue;
		}
	      return -1;
	    }
	  if ( cnt == 0 )
	    return 0;
	  bp = b;
	}
      c = *bp++;
      *bufptr++ = c;
      if ( c == '\n' )
	{
	  *bufptr = '\0';
	  return bufptr - bufx;
	}
    }
  errno = EMSGSIZE;
  return -1;
}
   
